package com.example.superoa.model.service;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;

import java.math.BigDecimal;
import java.sql.Time;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.example.superoa.common.Shijian;
import com.example.superoa.model.dao.KqAttendanceMonthDao;
import com.example.superoa.model.dao.KqBanciDao;
import com.example.superoa.model.dao.StaffDao;
import com.example.superoa.model.mappers.AttendMapper;
import com.example.superoa.model.mappers.AttendMonthMapper;
import com.example.superoa.model.mappers.BusinessMapper;
import com.example.superoa.model.mappers.DemoMapper;
import com.example.superoa.model.mappers.LeaveMapper;
import com.example.superoa.model.mappers.OvertimeMapper;
import com.example.superoa.model.mappers.OvertimestatiMapper;
import com.example.superoa.model.mappers.RecessMapper;
import com.example.superoa.model.pojos.KqAttendanceMonth;
import com.example.superoa.model.pojos.KqBanci;
import com.example.superoa.model.pojos.Staff;

@Service
@Transactional(rollbackFor=Exception.class)
public class AttendMonthService {
	@Autowired
	private KqAttendanceMonthDao m_dao;
	
	@Autowired
	private LeaveService l_ser;
	
	@Autowired
	private BusinessService b_ser;
	
	@Autowired
	private OvertimeService o_ser;
	
	@Autowired
	private AttendMonthMapper m_map;
	@Autowired
	private AttendMapper a_map;
	
	@Autowired
	private OvertimeMapper o_map;
	
	@Autowired
	private KqBanciDao b_dao;
	
	@Autowired
	private BusinessMapper b_map;
	
	@Autowired
	private RecessMapper r_map;
	
	@Autowired 
	private DakaService d_ser;
	
	@Autowired
	private OvertimestatiMapper os_map;
	
	@Autowired
	private LeaveMapper l_map;
	
	@Autowired
	private StaffDao s_dao;
	
	 Shijian sj=new Shijian();
	
	//查看每个员工是否有本月数据 没有则加上
	public void selectMont(Date date) {
		List<Integer> list=sj.getyearmonth(date);
		int year=list.get(0);
		int mon=list.get(1);
		List<Integer> month=m_map.selectYMdate(year,mon);
		List<Integer> staff=m_map.selectStaff();
		Set<Integer> set1=new HashSet<>();
		Set<Integer> set2=new HashSet<>();
		int yingchu=sj.getYingchu(sj.getMonthday(year, mon),m_map.selectjiaQi(mon),year, mon);
		for (Integer o : staff) {
				if(month.size()==0) {
						set2.add(o);
				}else {
					for (Integer obj : month) {
						if(obj==o) {
							set1.add(o);
						}
					}
				}
		}
			Integer id = null;
			try {
				id=m_map.selectmonthid()+1;
			} catch (Exception e) {
				
			}
			if(id==null) {
				id=1;
			}
			//法定假
			JSONArray one=r_map.selectjiaTow();
			//公司假
			JSONArray tow=r_map.selectjiathree();
			for (Integer integer : set1) {
				JSONArray jia=o_map.selectOvertimeStaff(integer);
				JSONObject kqmonth=m_map.selectmonth(year, mon, integer);
				Staff staff1=s_dao.findById(integer).get();
				update(2,kqmonth.getInteger("AM_ID"),date,yingchu,staff1,year,mon,selectChu(new Date(sj.getNetworkTime()),staff1,one,tow,jia));
			}
			for (Integer i : set2) {
				JSONArray jia=o_map.selectOvertimeStaff(i);
				Staff staff1=s_dao.findById(i).get();
				update(1,id,date,yingchu,staff1,year,mon,selectChu(new Date(sj.getNetworkTime()),staff1,one,tow,jia));
				id++;
			}
			
	}
	//给月报表赋值
	public void update(int ss,int id,Date date,int yingchu,Staff staff,Integer year,Integer mon,JSONObject ob) {
		//创建一个新的月报对象
		KqAttendanceMonth m=new KqAttendanceMonth();
		//算出输入年，月的所有的实出勤天（chu），迟到（chi），早退（zaotui），旷工（kuang）
		JSONObject object=m_map.selectChuStaff(year,mon,staff.getStaffId());
		//设置变量
		BigDecimal ling=new BigDecimal(0);
		BigDecimal gongjia,xiujia,jiejia,shichu,chi,zaotui,kuanggong,qing;
		gongjia=ling;
		xiujia=ling;
		jiejia=ling;
		Integer chu;
		//预防空指针报错
		if(ob.get("chuchai")==null) {
			chu=0;
		}else {
			chu=ob.getInteger("chuchai");
		}
		try {
			if(object.get("chu")==null) {
				shichu=new BigDecimal(0);
			}else {
				shichu=object.getBigDecimal("chu");
			}
		} catch (Exception e) {
			shichu=new BigDecimal(0);
		}
		if(ss==1) {
			m.setAmMonth(new Date(sj.getNetworkTime()));
		}else {
			m.setAmMonth(date);
		}
		try {
			if(object.get("chi")==null) {
				chi=new BigDecimal(0);
			}else {
				chi=object.getBigDecimal("chi");
			}
		} catch (Exception e) {
			chi=new BigDecimal(0);
		}
		try {
			if(object.get("zaotui")==null) {
				zaotui=new BigDecimal(0);
			}else {
				zaotui=object.getBigDecimal("zaotui");
			}
		} catch (Exception e) {
			zaotui=new BigDecimal(0);
		}
		try {
			if(object.get("kuang")==null) {
				kuanggong=new BigDecimal(0);
			}else {
				kuanggong=object.getBigDecimal("kuang");
			}
		} catch (Exception e) {
			kuanggong=new BigDecimal(0);
		}
		if(gongjia==null) {
			gongjia=new BigDecimal(0);
		}
		if(xiujia==null) {
			xiujia=new BigDecimal(0);
		}
		if(jiejia==null) {
			jiejia=new BigDecimal(0);
		}
		
		if(ob.get("Qing")==null) {
			qing=new BigDecimal(0);
		}else {
			qing=ob.getBigDecimal("Qing");
		}
		//相加
		kuanggong=kuanggong.add(ob.getBigDecimal("kuang"));
		gongjia=gongjia.add(ob.getBigDecimal("pingjia"));
		xiujia=xiujia.add(ob.getBigDecimal("xiujia"));
		jiejia=jiejia.add(ob.getBigDecimal("jiejia"));
		if(sj.getyuefen(date, staff.getDateentry())) {
			selectYingchu(yingchu, date);
		}
		//赋值
		m.setAmId(id);
		m.setStaff(staff);	
		m.setAmShichu(shichu);
		m.setAmChi(chi);
		m.setAmTui(zaotui);
		m.setAmGongjia(gongjia);
		m.setAmXiujia(xiujia);
		m.setAmJiejia(jiejia);
		m.setAmYingchu(yingchu);
		m.setAmQing(qing);
		m.setAmChu(chu);
		m.setAmKuang(kuanggong);
		m.setAmQue(ob.getBigDecimal("que"));
		m_dao.save(m);
		d_ser.upaddOS(staff, ob, date);
	}
	public JSONArray selectShi(int year,int month,Integer staffid) {
		return m_map.selectmonthAll(year,month,staffid);
	}
	public JSONArray selectmonthId(int year,int month,int staff_id) {
		return m_map.selectmonthId(year, month, staff_id);
	}
	public List<Date> selectMonth(){
		return m_map.selectMonth();
	}
	//查看输入日期是否为假期
	public boolean selectPanduancs(Date date,JSONArray object) {
		boolean opin=false;
		for (Object obj : object) {
			JSONObject o=(JSONObject) obj;
			if(sj.getPanduan(date, o.getDate("RE_KAI"), o.getDate("RE_JIE"))) {
				opin=true;
			}
		}
		return opin;
	}
	//通过输入入职日期来计算应出勤应减去多少
	public Integer selectYingchu(Integer ying,Date date) {
		List<Integer> list=sj.getyearmonth(date);
		JSONArray one=a_map.selelcttow(1);
		JSONArray two=a_map.selelcttow(2);
		SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
		for (String str : sj.getDayByMonth(list.get(0), list.get(1)-1, list.get(2), 2)) {
			Date day = null;
			try {
				day=sdf.parse(str);
			} catch (ParseException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			if(!selectPanduancs(day,one)&&!selectPanduancs(day,two)&&!sj.panduanSun(day)) {
				ying=ying-1;
			}
		}
		return ying;
	}
	public String select(Integer id) {
		List<String> set=m_map.selectpname(id);
		String str="";
		for (String string : set) {
			str+=" "+string;
		}
		return str;
	}
	//计算月报信息
	public JSONObject selectChu(Date date,Staff staff,JSONArray one,JSONArray tow,JSONArray jia) {
		List<String> day;
		//通过员工id查询所有出差记录
		JSONArray Chu=b_map.selectMonthAll(staff.getStaffId());
		//通过员工id查询所有考勤记录
		JSONArray kao=a_map.selectattendStaff(staff.getStaffId());
		//通过员工id查询所有请假记录
		JSONArray qing=l_map.selectQingjia(staff.getStaffId());
		//把输入日期分割为年，月，日
		List<Integer> list=sj.getyearmonth(date);
		//根据输入年，月，员工id查询输入月的月加班记录
		JSONObject obj=os_map.selectOverstatiId(list.get(0), list.get(1), staff.getStaffId());
		if(sj.getyuefen(date, staff.getDateentry())) {
			day=new ArrayList();
			SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
			for (Date d : sj.getDays(1, staff.getDateentry(), date)) {
				day.add(sdf.format(d));
			}
		}else {
			day=sj.getDayByMonth(list.get(0), list.get(1)-1,list.get(2),2);
		}
		//判断输入时间是否为本月，是则查询输入日期之前的所有本月已过天数的所有记录，否则查询输入月的所有天数记录
		return selectAll(day,date,Chu,2,one,tow,staff,list,obj,jia,kao,qing);
	}
	//查询个人考勤详情
	public JSONArray selectMonthXiang(Integer id,Date ruzhi,Date date,JSONArray one,JSONArray tow) {
		SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
		List<Integer> time=sj.getyearmonth(date);
		List<String> list=sj.getDayByMonth(time.get(0), time.get(1)-1,1,1);
		JSONArray array=new JSONArray();
		//通过员工id查询所有出差记录
		JSONArray Chu=b_map.selectMonthAll(id);
		//通过员工id查询所有考勤记录
		JSONArray kao=a_map.selectattendStaff(id);
		//通过员工id查询所有请假记录
		JSONArray leave=l_map.selectQingjia(id);
		
		JSONArray jia=o_map.selectOvertimeStaff1(id);
		int i=1;
		for (String string : list) {
			JSONObject  obj=new JSONObject();
			Date day = null;
			boolean opin=false;
			JSONObject atten=null;
			int jiaban=0;
			try {
				day=sdf.parse(string);
			} catch (ParseException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			if(sj.getPanduanShi2(day, ruzhi)>0) {
				//通过查看假期表，判断今天是否放法定假
				for (Object o2 : one) {
					JSONObject objjj=(JSONObject)o2;
					if(sj.belongCalendar(day, objjj.getDate("RE_KAI"), objjj.getDate("RE_JIE"), 1)) {
						opin=true;
						break;
					}
				}
				//通过查看假期表，判断今天是否放公司假
				for (Object o2 : tow) {
					JSONObject objjj=(JSONObject)o2;
					if(sj.belongCalendar(day, objjj.getDate("RE_KAI"), objjj.getDate("RE_JIE"), 2)) {
						opin=true;
						break;
					}
				}
				//通过查询请假，
				for (Object o2 : leave) {
					JSONObject objjj=(JSONObject)o2;
					//判断今天是否请假
					if(sj.belongCalendar(day, objjj.getDate("L_KAI"), objjj.getDate("L_JIE"), 2)) {
						//判断请假时间段是否为全天,是则请假+1，否则+0.5并且判断当天是否有考勤记录
						if(objjj.getInteger("L_CLASS")==1) {
							obj.put("ban", "全天请假");
						}else if(objjj.getInteger("L_CLASS")==2){
							obj.put("ban", "上午请假");
						}else {
							obj.put("ban", "下午请假");
						}
						break;
					}
				}
				//查看考勤记录，判断今天是否有考勤
				for (Object o1 : kao) {
					JSONObject objj=(JSONObject)o1;
					//如果有，则把今天考勤记录存储
					if(sj.getPanduanShi2(objj.getDate("a_date"), day)==0) {
						atten=objj;
						break;
					}
				}
				//查看加班记录
				for (Object object : jia) {
					JSONObject objj=(JSONObject)object;
					//如果有，则记录
					if(sj.belongCalendar(day, objj.getDate("O_KAI"), objj.getDate("O_JIE"), 2)) {
						jiaban=1;
						break;
					}
				}
				if(atten!=null) {
					obj.put("dao",atten.getString("a_dao"));
					obj.put("tui", atten.getString("a_tui"));
					if(obj.get("ban")==null) {
						if(atten.getInteger("a_ban")==1&&atten.getString("a_dao")!=null&&atten.getString("a_tui")!=null) {
							if(jiaban==1) {
								obj.put("ban","加班");
							}else {
								obj.put("ban","正常");
							}
						}else{
							obj.put("ban","异常");
						}
					}
					obj.put("why", atten.getString("a_why"));
					obj.put("shichu", atten.getString("a_shichu"));
				}else {
					obj.put("dao","");
					obj.put("tui", "");
					if(day.compareTo(new Date(sj.getNetworkTime()))==1) {
						obj.put("ban","未开始");
					}else {
						//查询所有出差记录
						for (Object o : Chu) {
							JSONObject ob=(JSONObject)o;
							//查看今天是否为出差
							if(sj.belongCalendar(day, ob.getDate("bus_kai"), ob.getDate("bus_jie"), 2)) {
								obj.put("ban", "出差");
								obj.put("why", ob.get("bus_why"));
							}
						}
					}
					obj.put("shichu", "");
				}
				if(sj.panduanSun(day)||opin) {
					obj.put("type", "休息");
					if(obj.get("ban")==null) {
						obj.put("ban", "无");
					}
				}else {
					obj.put("type", "上班");
					if(obj.get("ban")==null) {
						obj.put("ban", "缺勤");
					}
				}
			}else {
				obj.put("type", "暂未入职");
				obj.put("ban", "无");
			}
			obj.put("sta", i);
			i++;
			obj.put("date", string);	
			array.add(obj);
		}	
		return array;
	}
	//主要计算，请假，加班，缺勤，额外出勤，出差,额外旷工。
	public JSONObject selectAll(List<String> list1,Date date,JSONArray chu,Integer type,JSONArray one,JSONArray tow,Staff staff,List<Integer> list,JSONObject object,JSONArray jia,JSONArray kao,JSONArray leave) {
		JSONObject arr=new JSONObject();
		Integer chuchai=0,shichu=0,pingjia=0,jiejia=0,xiujia=0,que=0;
		BigDecimal qing=new BigDecimal(0),kuang=new BigDecimal(0);
		SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
		//循环所有天数
		for (String string : list1) {
			boolean opin=false;
			Date day = null;
			JSONObject jsonobje=null;
			try {
				day=sdf.parse(string);
			} catch (ParseException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			//查看考勤记录，判断今天是否有考勤
			for (Object o1 : kao) {
				JSONObject objj=(JSONObject)o1;
				//如果有，则把今天考勤记录存储
				if(sj.getPanduanShi2(objj.getDate("a_date"), day)==0) {
					opin=true;
					jsonobje=objj;
					break;
				}
			}
			//通过查询请假，
			for (Object o2 : leave) {
				JSONObject objjj=(JSONObject)o2;
				//判断今天是否请假
				if(sj.belongCalendar(day, objjj.getDate("L_KAI"), objjj.getDate("L_JIE"), 2)) {
					//判断请假时间段是否为全天,是则请假+1，否则+0.5并且判断当天是否有考勤记录
					opin=true;
					if(objjj.getInteger("L_CLASS")==1) {
						qing=qing.add(new BigDecimal(1));
						break;
					}else {
						qing=qing.add(new BigDecimal(0.5));
						if(jsonobje==null) {
							kuang=kuang.add(new BigDecimal(0.5));
						}
						break;
					}
				}
			}
			//通过查看假期表，判断今天是否放法定假
			for (Object o2 : one) {
				JSONObject objjj=(JSONObject)o2;
				if(sj.belongCalendar(day, objjj.getDate("RE_KAI"), objjj.getDate("RE_JIE"), 1)) {
					opin=true;
					break;
				}
			}
			//通过查看假期表，判断今天是否放公司假
			for (Object o2 : tow) {
				JSONObject objjj=(JSONObject)o2;
				if(sj.belongCalendar(day, objjj.getDate("RE_KAI"), objjj.getDate("RE_JIE"), 2)) {
					opin=true;
					break;
				}
			}
			//查询所有出差记录
			ok:for (Object o : chu) {
				JSONObject obj=(JSONObject)o;
				//查看今天是否为出差
				if(sj.belongCalendar(day, obj.getDate("bus_kai"), obj.getDate("bus_jie"), 2)) {
					//循环所有公司假
					for (Object o1 : tow) {
						JSONObject objj=(JSONObject)o1;
						//判断今天是否为公司假,如果是则为休息日加班，休息日加班时间+8，出差天数+1，并且今天不为缺勤
						if(sj.belongCalendar(day, objj.getDate("RE_KAI"), objj.getDate("RE_JIE"), 2)) {
							xiujia+=8;
							chuchai+=1;
							opin=true;
							break ok;
						}
					}
					//循环所有法定假
					for (Object o2 : one) {
						JSONObject objj=(JSONObject)o2;
						//判断今天是否为法定假,如果是则为节假日加班，节假日加班时间+8，出差天数+1，并且今天不为缺勤
						if(sj.belongCalendar(day, objj.getDate("RE_KAI"), objj.getDate("RE_JIE"), 1)) {
							jiejia+=8;
							chuchai+=1;
							opin=true;
							break ok;
						}
					}
					//判断今天是否为周末,如果是则为休息日加班，休息日加班时间+8，出差天数+1，并且今天不为缺勤
					if(sj.panduanSun(day)) {
						xiujia+=8;
						chuchai+=1;
						opin=true;
						break ok;
					}
					//运行到这代表，今天不为周末，则为平时上班，实际出勤天+1，出差天数+1，并且今天不为缺勤
					shichu+=1;
					chuchai+=1;
					opin=true;
					break ok;
				}
			}
			//判断今天是否有考勤记录
			if(jsonobje!=null) {
				//循环加班记录
				for (Object o2 : jia) {
					JSONObject objjj=(JSONObject)o2;
					//判断今天是否申请了加班申请单而且批准
					if(sj.belongCalendar(day,objjj.getDate("O_KAI"),objjj.getDate("O_JIE"),2)) {
						//计算加班时间
						if(jsonobje.get("a_dao")!=null&&jsonobje.get("a_tui")!=null) {
							if(objjj.getInteger("OX_TYPE")==0) {
								pingjia+=getJiaStaff(1,jsonobje,objjj.getInteger("OX_TIME")).intValue();
							}else if(objjj.getInteger("OX_TYPE")==1){
								xiujia+=getJiaStaff(2,jsonobje,objjj.getInteger("OX_TIME")).intValue();
							}else {
								jiejia+=getJiaStaff(3,jsonobje,objjj.getInteger("OX_TIME")).intValue();
							}
						}
					}
				}
			}
			//通过以上判断与今天是否周末来看他今天是否缺勤
			if(!opin) {
				if(!sj.panduanSun(day)) {
					que=que+1;
				}
			}
		}
		arr.put("kuang", kuang);
		arr.put("Qing", qing);
		arr.put("chuchai", chuchai);
		arr.put("pingjia", pingjia);
		arr.put("xiujia", xiujia);
		arr.put("jiejia", jiejia);
		arr.put("shichu", shichu);
		arr.put("que", que);
		return arr;
	}
	//加班时间计算
	public BigDecimal getJiaStaff(int type,JSONObject obj,Integer time) {
		System.out.println(obj);
		Time dao=new Time(obj.getDate("a_dao").getTime());
		Time tui=new Time(obj.getDate("a_tui").getTime());
		KqBanci banci=b_dao.findById(obj.getInteger("b_id")).get();
		//type为1，则是平时加班，把开始时间改为正常下班时间,结束时间改为正常下班时间的申请加班小时之后
		if(type==1) {
			banci.setBDao(banci.getBTui());
			banci.setBTui(new Time(sj.getDaiTime(banci.getBTui(),time).getTime()));
		}
		return sj.getShichu(dao, tui, banci);
	}
	
}
